import 'dart:async';
import 'dart:isolate';
import 'package:flutter/services.dart';

class SafeIsolate {
  static Future<T> run<T, P>(
    Future<T> Function(P) function, 
    P parameter,
  ) async {
    final receivePort = ReceivePort();
    final errorPort = ReceivePort();
    
    // 获取主 isolate 的 token
    final token = RootIsolateToken.instance!;
    
    try {
      await Isolate.spawn(
        _isolateEntry,
        _IsolateData<P, T>(
          function: function,
          parameter: parameter,
          sendPort: receivePort.sendPort,
          token: token,
        ),
        onError: errorPort.sendPort,
        onExit: receivePort.sendPort,
      );
    } catch (e) {
      throw Exception('无法启动isolate: $e');
    }
    
    final completer = Completer<T>();
    
    receivePort.listen((message) {
      if (message is _IsolateResult<T>) {
        if (message.error != null) {
          completer.completeError(
            message.error!, 
            message.stackTrace
          );
        } else {
          completer.complete(message.result);
        }
        receivePort.close();
        errorPort.close();
      }
    });
    
    errorPort.listen((error) {
      completer.completeError(Exception('Isolate错误: $error'));
      receivePort.close();
      errorPort.close();
    });
    
    return completer.future;
  }

  static void _isolateEntry<P, T>(_IsolateData<P, T> data) async {
    // 关键：初始化后台通信
    BackgroundIsolateBinaryMessenger.ensureInitialized(data.token);
    
    try {
      final result = await data.function(data.parameter);
      Isolate.exit(
        data.sendPort, 
        _IsolateResult<T>(result: result)
      );
    } catch (e, st) {
      Isolate.exit(
        data.sendPort, 
        _IsolateResult<T>(error: e, stackTrace: st)
      );
    }
  }
}

class _IsolateData<P, T> {
  final Future<T> Function(P) function;
  final P parameter;
  final SendPort sendPort;
  final RootIsolateToken token;
  
  _IsolateData({
    required this.function,
    required this.parameter,
    required this.sendPort,
    required this.token,
  });
}

class _IsolateResult<T> {
  final T? result;
  final Object? error;
  final StackTrace? stackTrace;
  
  _IsolateResult({
    this.result,
    this.error,
    this.stackTrace,
  });
}